Verrous
-
Verrou implicite (synchronisation via
synchronized)
Le mot-clésynchronizedest la méthode la plus simple pour verrouiller une section de code. Il permet de s'assurer qu'un seul thread accède à un bloc de code ou à une méthode à la fois.Exemple :
public class Compteur {private int count = 0;// Méthode synchronisée pour éviter les conditions de coursepublic synchronized void increment() {count++;}public synchronized int getCount() {return count;}}Pourquoi l'utiliser ?
Ce verrou est utile pour garantir que les modifications sur une ressource partagée (par exemple, une variable) ne soient pas effectuées simultanément par plusieurs threads. Cela permet de prévenir les incohérences. -
Verrou explicite (
LocketReentrantLock)
ReentrantLockest une classe de la bibliothèquejava.util.concurrent.locksqui offre plus de contrôle et de flexibilité par rapport àsynchronized. Contrairement àsynchronized, qui verrouille une méthode ou un bloc de code entier,ReentrantLockpermet de verrouiller manuellement une section de code et de déverrouiller explicitement le verrou à l'aide de méthodes commelock()etunlock().Exemple :
import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Compteur {private int count = 0;private final Lock lock = new ReentrantLock();public void increment() {lock.lock(); // Acquisition du verroutry {count++;} finally {lock.unlock(); // Libération du verrou}}public int getCount() {lock.lock();try {return count;} finally {lock.unlock();}}}Pourquoi l'utiliser ?
Ce verrou est préféré dans des scénarios où il est nécessaire de contrôler le verrouillage de manière plus fine, par exemple, pour utiliser des fonctionnalités commetryLock()ou pour implémenter des mécanismes plus complexes de gestion des verrouillages. -
Verrou
ReadWriteLockReadWriteLockpermet de séparer les verrous en deux types : un verrou pour les lectures et un verrou pour les écritures. Cela permet de permettre à plusieurs threads de lire simultanément une ressource partagée tout en interdisant l'accès en écriture pendant la lecture, et inversement.Exemple avec
ReentrantReadWriteLock:import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantReadWriteLock;public class Compteur {private int count = 0;private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();public void increment() {Lock writeLock = rwLock.writeLock();writeLock.lock();try {count++;} finally {writeLock.unlock();}}public int getCount() {Lock readLock = rwLock.readLock();readLock.lock();try {return count;} finally {readLock.unlock();}}}Pourquoi l'utiliser ?
Ce verrou est particulièrement utile lorsque les ressources partagées sont fréquemment lues et rarement écrites. Il permet de maximiser les performances en autorisant l'accès concurrent aux ressources en lecture tout en excluant les écritures simultanées.
Comparaison
-
synchronizedest simple et direct, mais il est limité dans ses capacités (pas de contrôle explicite sur l'acquisition et la libération du verrou, pas de temps d'attente ou de tentatives de verrouillage). -
ReentrantLockoffre plus de flexibilité et permet des fonctionnalités avancées commetryLock(),lockInterruptibly(), ou même des verrouillages temporisés. -
ReadWriteLockest parfait lorsque l'accès en lecture est beaucoup plus fréquent que l'accès en écriture, ce qui permet d'optimiser les performances en cas de lecture concurrente.